
#include "voice_common.h"
#include "gkt_dac.h"

enum {
	VOICE_OUTPUT_HW_ST_NOT_INIT = 0,
	VOICE_OUTPUT_HW_ST_INIT,
	VOICE_OUTPUT_HW_ST_START,
	VOICE_OUTPUT_HW_ST_MAX
};

typedef struct voice_output_hw_gk1903 {
	uint32_t	state;

	uint32_t	left_blocks;
	int	cycle_mode;
	int	to_decode_padding_mute_block;
	int	dac_start;
} voice_output_hw_gk1903_s;
static voice_output_hw_gk1903_s s_voice_output_hw_gk1903;
static voice_output_s *s_voice_output;

static void voice_output_dac_callback(void)
{
	gkt_trace("dac callback: block=%d\n", s_voice_output_hw_gk1903.left_blocks);
	if (s_voice_output_hw_gk1903.left_blocks > 0) {
		s_voice_output_hw_gk1903.left_blocks--;
		voice_output_decode_blocks(s_voice_output);
		gkt_dac_control(GKT_DAC_CONTROL_TYPE_FINISHED);
	}
	else {
		s_voice_output_hw_gk1903.dac_start = 0;
		gkt_dac_control(GKT_DAC_CONTROL_TYPE_STOP);
		gkt_dac_off();
		voice_output_status_notify(VOICE_OUTPUT_ST_END);
	}
}

int voice_output_hw_init(voice_output_s *output)
{
	int retval;

	s_voice_output = output;
	// TODO:
	// G_DAC_Init
	retval = gkt_dac_init();
	if (retval != GKT_SUCCESS) {
		gkt_error("voice_output_dac_init: failed. retval=%d\n", retval);
		return GKT_ECREATE;
	}
	gkt_dac_register_irq_callback(voice_output_dac_callback);

	s_voice_output_hw_gk1903.state = VOICE_OUTPUT_HW_ST_INIT;

	return retval;
}

int voice_output_hw_start(uint8_t volume_level, const uint8_t *data, uint32_t size)
{
	int retval = GKT_SUCCESS;
	const uint8_t volume[] = {GKT_DAC_VOICE_VOLUME_HIGH, GKT_DAC_VOICE_VOLUME_MIDDLE, GKT_DAC_VOICE_VOLUME_LOW};
	uint32_t dac_size, total_frames, total_blocks;

	gkt_trace("voice_output_hw_start: state=%d, size=%d, BUFFER_SIZE=%d\n", 
			s_voice_output_hw_gk1903.state, size, VOICE_OUTPUT_DEC_BUFFER_SIZE);
	if (VOICE_OUTPUT_HW_ST_INIT == s_voice_output_hw_gk1903.state) {
		total_frames = (size /GKT_VOICE_DEC_CONVERSION_SAMPLE_MULTIPLE) / (VOICE_OUTPUT_DEC_FRAME_BYTES);
		total_blocks = (total_frames + VOICE_OUTPUT_DEC_BLOCK_FRAMES - 1) / VOICE_OUTPUT_DEC_BLOCK_FRAMES;

		if (total_blocks >= VOICE_OUTPUT_DEC_BLOCK_NUMS)
			s_voice_output_hw_gk1903.left_blocks = total_blocks - VOICE_OUTPUT_DEC_BLOCK_NUMS;
		else
			s_voice_output_hw_gk1903.left_blocks = 0;

		gkt_trace("voice_output_hw_start: total_blocks=%d, left_blocks=%d\n",
			total_blocks, s_voice_output_hw_gk1903.left_blocks);
		if (size <= VOICE_OUTPUT_DEC_BUFFER_SIZE)
			dac_size = size;
		else
			dac_size = VOICE_OUTPUT_DEC_BUFFER_SIZE;
		s_voice_output_hw_gk1903.cycle_mode = 1;
		s_voice_output_hw_gk1903.to_decode_padding_mute_block = 0;

		gkt_trace("voice_output_hw_start: gkt_dac_start cycle_mode=%d\n", 
							s_voice_output_hw_gk1903.cycle_mode);
		gkt_dac_start(volume[volume_level], data, dac_size, 
			s_voice_output_hw_gk1903.cycle_mode, GKT_VOICE_DEC_CONVERSION_SAMPLE_MULTIPLE*0xF0, GKT_VOICE_DEC_CONVERSION_SAMPLE_MULTIPLE);
		s_voice_output_hw_gk1903.dac_start = 1;

		s_voice_output_hw_gk1903.state = VOICE_OUTPUT_HW_ST_START;
	}
	else if (VOICE_OUTPUT_HW_ST_START == s_voice_output_hw_gk1903.state)
		retval = GKT_EALREADY;
	else
		retval = GKT_ENOTINIT;

	return retval;
}

void voice_output_hw_stop(void)
{
	if (VOICE_OUTPUT_HW_ST_START == s_voice_output_hw_gk1903.state) {
		if (s_voice_output_hw_gk1903.dac_start) {
			s_voice_output_hw_gk1903.dac_start = 0;
			gkt_dac_control(GKT_DAC_CONTROL_TYPE_STOP);
			gkt_dac_off();
			gkt_voice_decode_stop();
		}
		s_voice_output_hw_gk1903.state = VOICE_OUTPUT_HW_ST_INIT;
	}
	
}
